﻿using System;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Core.ProxyService;
using System.Collections.Generic;
using Api.Model;
using System.Threading;
using Services = System.Collections.Generic.IEnumerable<Core.ProxyService.ICoreProxyService>;
using Articles = System.Collections.Generic.IEnumerable<Api.Model.Article>;

namespace CompositeProxyService
{
    public class CompositeProxyService : NotPaginatedProxyService
    {
        private static readonly Object syncRoot = new object();

        private Services services;
        private List<Article> articles;
        private int errorCount;
        private int requestCompleted;

        public CompositeProxyService(params ICoreProxyService[] services)
        {
            this.services = services;
        }

        public override void GetArticlesAsync(Action<ArticlesDownloadedEventArgs> callback)
        {
            base.GetArticlesAsync(callback);

            articles = new List<Article>();
            requestCompleted = 0;
            errorCount = 0;

            foreach (var service in services)
            {
                SendRequestAsync(service, callback);
            }
        }

        private void SendRequestAsync(ICoreProxyService service, Action<ArticlesDownloadedEventArgs> finalCallback)
        {
            service.GetArticlesAsync(args =>
                {
                    HandleSingleResponse(finalCallback, args);
                });
        }

        private void HandleSingleResponse(Action<ArticlesDownloadedEventArgs> finalCallback, ArticlesDownloadedEventArgs args)
        {
            lock (syncRoot)
            {
                requestCompleted++;

                if (args.Error == null && !args.Cancelled)
                {
                    articles.AddRange(args.Result);
                }
                else
                {
                    errorCount++;
                }

                if (errorCount == services.Count())
                {
                    var finalArgs = new ArticlesDownloadedEventArgs(new Exception("All services failed, cannot load any article"), false, null, null);
                    finalCallback(finalArgs);
                }
                else if (requestCompleted == services.Count())
                {
                    var finalArgs = new ArticlesDownloadedEventArgs(null, false, null, articles);
                    finalCallback(finalArgs);
                }
            }
        }
    }
}
